/*
 * @Descripttion: 函数公共方法集
 * @Author: yeming
 * @Date: 2018-06-05 15:51:42
 */

/* eslint-disable */
const O = {}

/**
 * @desc 校验是否银行卡号
 * @param {str} inp 银行卡号
 * @return {Boolean} 校验结果
 */
O.regBankCard = function (inp) {
  let reg = /^(\d{16,19})$/g;
  let cardNumber = inp.replace(/\s+/g, "");
  if (!reg.test(cardNumber)) {
    return false;
  } else {
    return true;
  }
};

/**
 * @desc 从url中拿指定的参数值
 * @param {str} name 要拿的参数名  字符
 * @param {str} url （选填，默认当前 url） 支持密文
 * @return {str} 参数值
 */
O.getQueryString = function (name, url) {
  let searchUrl = window.location.search;
  if (url) {
    searchUrl = url.indexOf("?") ? url.substr(url.indexOf("?")) : searchUrl;
  }
  let reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)", "i");
  let r = searchUrl.substr(1).match(reg);
  if (r !== null) {
    return decodeURIComponent(r[2]);
  }
  return "";
};

/**
 * @desc 从页面url中获取json（url是未被编码的明文格式）
 * <pre> url格式：http://www.baidu.com?action=1&toobar=0
 * @param {str} url  页面的url，（url是未被编码的明文格式）
 * @returns {obj} json    json对象
 */
O.getQueryJson = function (url) {
  let json = {};
  if (url) {
    let splits = url.split("?");
    if (splits && splits.length >= 2) {
      let array = splits[1].split("&");
      if (array && array.length > 0) {
        for (let i = 0; i < array.length; i++) {
          let params = array[i].split("="); // 拆分形式为key=value形式的参数
          json[params[0]] = params[1]; // 第一个参数表示key，第二个参数表示value
        }
      }
    }
  }
  return json;
};

/**
 * @desc 根据对象键进行排序
 * @param {obj} obj  对象数据
 * @returns {obj} params 新对象
 */
O.objKeySort = function (obj) {
  //【1】用Object内置类的keys方法获取要排序对象的属性名
  //【2】用Array原型上的sort方法对获取的属性名进行排序，返回一个新数组newkey 
  var newkey = Object.keys(obj).sort();
  var newObj = {}; // 创建一个新的对象，用于存放排好序的键值对 
  for (var i = 0; i < newkey.length; i++) { // 遍历newkey数组
    newObj[newkey[i]] = obj[newkey[i]]; // 向新创建的对象中按照排好的顺序依次增加键值对 ，
    // newObj[newkey[i].toLowerCase()] = obj[newkey[i]]; 并大写转换小写【做签名验证会用】
  }
  return newObj; // 返回排好序的新对象 
}

/**
 * @desc 根据对象键的值进行排序
 * @param {str} filed  对象键
 * @param {boolean} rev
 * @returns {undefined}} primer 类型不定，根据传入来确定
 * @use var obj = [{ b: '3', c: 'c' },{ b: '1', c: 'a' },{ b: '2', c: 'b' }]; obj.sort(sortBy('b', false, parseInt));
 * @use console.log(obj);
 */
O.sortBy = function (filed, rev, primer) {
  rev = (rev) ? -1 : 1;
  return function (a, b) {
    a = a[filed];
    b = b[filed];
    if (typeof (primer) != 'undefined') {
      a = primer(a);
      b = primer(b);
    }
    if (a < b) { return rev * -1; }
    if (a > b) { return rev * 1; }
    return 1;
  }
};

/**
 * @desc 对象格式转 & 拼接字符串
 * @param {obj} params  对象数据
 * @returns {str} string
 */
O.getObjStr = function (params) {
  let newParams = O.objKeySort(params);
  let str = '';
  let temp = [];
  for (var Key in newParams) {
    temp.push(Key + "=" + params[Key]);
  }
  str = temp.join("&");
  return str;
};

/**
 * @desc 邮箱判断
 * @param {str} email 邮箱
 * @return {bool} 校验结果
 */
O.checkEmail = function (email) {
  const patten = /^([a-zA-Z0-9]+[_|_|\-|.]?)*[a-zA-Z0-9]+@([a-zA-Z0-9]+[_|_|.]?)*[a-zA-Z0-9]+\.[a-zA-Z]{2,3}$/;
  if (!patten.test(email)) {
    return false;
  } else {
    return true;
  }
};

/**
 * @desc 校验身份证，包含 一代 和 二代  身份证校验
 * @param {str} idCard 身份证号
 * @return {bool} 校验结果
 */
O.checkIdCard = function (idCard) {
  idCard = idCard.toUpperCase();
  // 身份证号码为15位或者18位，15位时全为数字，18位前17位为数字，最后一位是校验位，可能为数字或字符X。
  if (!/(^\d{15}$)|(^\d{17}([0-9]|X)$)/.test(idCard)) {
    return false;
  }
  // 校验位按照ISO 7064:1983.MOD 11-2的规定生成，X可以认为是数字10。
  // 下面分别分析出生日期和校验位
  let len;
  let re;
  let arrSplit;
  let dtmBirth;
  let arrInt;
  let arrCh;
  let bGoodDay;
  let nTemp = 0;
  len = idCard.length;
  if (len === 15) {
    re = new RegExp(/^(\d{6})(\d{2})(\d{2})(\d{2})(\d{3})$/);
    arrSplit = idCard.match(re);

    // 检查生日日期是否正确
    dtmBirth = new Date(
      "19" + arrSplit[2] + "/" + arrSplit[3] + "/" + arrSplit[4]
    );
    bGoodDay =
      dtmBirth.getYear() === Number(arrSplit[2]) &&
      dtmBirth.getMonth() + 1 === Number(arrSplit[3]) &&
      dtmBirth.getDate() === Number(arrSplit[4]);
    if (!bGoodDay) {
      // $toast("请输入有效的证件号码！",1500);
      return false;
    } else {
      // 将15位身份证转成18位
      // 校验位按照ISO 7064:1983.MOD 11-2的规定生成，X可以认为是数字10。
      arrInt = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2];
      arrCh = ["1", "0", "X", "9", "8", "7", "6", "5", "4", "3", "2"];
      idCard = idCard.substr(0, 6) + "19" + idCard.substr(6, idCard.length - 6);
      for (var i = 0; i < 17; i++) {
        nTemp += idCard.substr(i, 1) * arrInt[i];
      }
      idCard += arrCh[nTemp % 11];
      return true;
    }
  }
  if (len === 18) {
    re = new RegExp(/^(\d{6})(\d{4})(\d{2})(\d{2})(\d{3})([0-9]|X)$/);
    arrSplit = idCard.match(re);

    // 检查生日日期是否正确
    dtmBirth = new Date(
      arrSplit[2] + "/" + arrSplit[3] + "/" + arrSplit[4]
    );
    bGoodDay =
      dtmBirth.getFullYear() === Number(arrSplit[2]) &&
      dtmBirth.getMonth() + 1 === Number(arrSplit[3]) &&
      dtmBirth.getDate() === Number(arrSplit[4]);
    if (!bGoodDay) {
      // $toast("请输入有效的证件号码！",1500);
      return false;
    } else {
      // 检验18位身份证的校验码是否正确。
      // 校验位按照ISO 7064:1983.MOD 11-2的规定生成，X可以认为是数字10。
      let valnum;
      arrInt = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2];
      arrCh = ["1", "0", "X", "9", "8", "7", "6", "5", "4", "3", "2"];
      for (var n = 0; n < 17; n++) {
        nTemp += idCard.substr(n, 1) * arrInt[n];
      }
      valnum = arrCh[nTemp % 11];
      if (valnum !== idCard.substr(17, 1)) {
        return false;
      }
      return true;
    }
  }
  return false;
};

/**
 * @desc 通过身份证号获取生日，性别
 * @param {str} idCard  身份证号码
 * @return {obj}  {birth: ", sex: "}
 */
O.getInfoByIdCard = function (idCard) {
  var rel = {};
  var tmpStr = "";
  var sexStr = "";
  idCard = idCard.replace(/\s*/g, "");
  if (idCard) {
    if (idCard.length === 15) {
      tmpStr = idCard.substring(6, 12);
      var year = tmpStr.substring(0, 2);
      if (parseInt(year) < 20) {
        tmpStr = "20" + tmpStr;
      } else {
        tmpStr = "19" + tmpStr;
      }
      tmpStr =
        tmpStr.substring(0, 4) +
        "-" +
        tmpStr.substring(4, 6) +
        "-" +
        tmpStr.substring(6);
      sexStr = parseInt(idCard.substr(14, 1), 10) % 2 ? "男" : "女";
    } else {
      tmpStr = idCard.substring(6, 14);
      tmpStr =
        tmpStr.substring(0, 4) +
        "-" +
        tmpStr.substring(4, 6) +
        "-" +
        tmpStr.substring(6);
      sexStr = parseInt(idCard.substr(16, 1), 10) % 2 ? "男" : "女";
    }
  } else {
    tmpStr = "";
    sexStr = "";
  }
  rel.birth = tmpStr;
  rel.sex = sexStr;
  return rel;
};

/**
 * @desc 通过身份证号获取年龄
 * @param {str} idCard 身份证号
 * @return {str} age 年龄
 */
O.getAgeByIdCard = function (idCard) {
  var age = "";
  var tmpStr = "";
  idCard = idCard.replace(/\s*/g, "");
  if (idCard.length === 15) {
    tmpStr = idCard.substring(6, 12);
    var year = tmpStr.substring(0, 2);
    if (parseInt(year) < 20) {
      tmpStr = "20" + tmpStr;
    } else {
      tmpStr = "19" + tmpStr;
    }
    tmpStr =
      tmpStr.substring(0, 4) +
      "-" +
      tmpStr.substring(4, 6) +
      "-" +
      tmpStr.substring(6);
  } else {
    tmpStr = idCard.substring(6, 14);
    tmpStr =
      tmpStr.substring(0, 4) +
      "-" +
      tmpStr.substring(4, 6) +
      "-" +
      tmpStr.substring(6);
  }
  age = this.getAgeByBirth(tmpStr);
  return age;
};

/**
 * @desc 根据出生日期获取年龄
 * @param {str} birthday 出生日期
 * @example 2000/12/03 2000-12-03
 * @return {num} 年龄
 */
O.getAgeByBirth = function (birthday) {
  var r = birthday.match(/^(\d{1,4})(-|\/)(\d{1,2})\2(\d{1,2})$/);
  if (r === null) {
    return false;
  }
  var birth = new Date(r[1], r[3] - 1, r[4]);
  if (
    birth.getFullYear() === Number(r[1]) &&
    birth.getMonth() + 1 === Number(r[3]) &&
    birth.getDate() === Number(r[4])
  ) {
    var today = new Date();
    today.setDate(today.getDate() + 1);
    var age = today.getFullYear() - r[1];
    if (today.getMonth() > birth.getMonth()) {
      return age;
    }
    if (today.getMonth() === birth.getMonth()) {
      if (today.getDate() >= birth.getDate()) {
        return age;
      } else {
        return age - 1;
      }
    }
    if (today.getMonth() < birth.getMonth()) {
      return age - 1;
    }
  }
  return age;
};

/**
 * @desc  根据身份证号判断性别
 * @param {str}  idCard  身份证号
 * @return {str} "男" "女"
 */
O.getSexByIdCard = function (idCard) {
  if (parseInt(idCard.substr(16, 1)) % 2 === 1) {
    return "男";
  } else {
    return "女";
  }
};

/**
 * @desc 字符串去空格
 * @param {str} str
 * @return {str} 去空格之后的字符串
 */
O.trimAll = function (str) {
  if (!str) {
    return "";
  }
  return str.replace(/\s+/g, "");
};

/**
 * @desc 计算字符串长度(英文占1个字符，中文汉字占2个字符)
 * @param {str} str
 * @return {num} 字符串长度
 */
O.getStrLen = function (str) {
  var strlength = str.length;
  for (var i = 0; i < str.length; i++) {
    if (str.charCodeAt(i) > 255) {
      // 判断输入的是否是汉字，如果是汉字的话，则字符串长度加2
      strlength += 1;
    }
  }
  return strlength;
};

/**
 * 校验手机号码
 * 非1开头的号码；
 * 重复数字超过7位（含7位）
 * 数字递增或递减超过7位（含7位）；
 * 两位数字组成的组合重复出现超4次 如13838383838
 * 13800138000
 * 含有非数字字符（如*#￥）；
 * @param {str} phone 手机号码
 * @return {obj} 校验结果 {result: bool, title: "} 当result是true时, 没有title
 */
O.checkPhone = function (phone) {
  if (phone === "") {
    return {
      result: false,
      title: "手机号不能为空"
    };
  }
  var reg = /^1[3,4,5,6,7,8,9]\d{9}$/;
  if (!reg.test(phone)) {
    return {
      result: false,
      title: "请正确输入手机号"
    };
  }
  var sub = phone.substr(2);
  var sub2 = phone.substr(3);
  var len = sub.length;
  var offset = 0;
  var num = 0;
  for (var i = len - 1; i > 0; i--) {
    var a = parseInt(sub[i]);
    var b = parseInt(sub[i - 1]);
    if (a - b === 1 || b - a === 1) {
      num++;
      if (num >= 6) {
        return {
          result: false,
          title: "请正确输入手机号"
        };
      }
    } else {
      num = 0;
    }
    if (a - b === 0) {
      offset++;
      if (offset >= 6) {
        return {
          result: false,
          title: "请正确输入手机号"
        };
      }
    } else {
      offset = 0;
    }
  }
  if (phone === "13800138000") {
    return {
      result: false,
      title: "请正确输入手机号"
    };
  }
  if (
    sub2[0] + sub2[1] === sub2[2] + sub2[3] &&
    sub2[4] + sub2[5] === sub2[6] + sub2[7] &&
    sub2[4] + sub2[5] === sub2[0] + sub2[1]
  ) {
    return {
      result: false,
      title: "请正确输入手机号"
    };
  }
  return {
    result: true
  };
};

/**
 * @desc 手机号 脱敏 补星 185 **** 4008
 * @param {str} phone
 * @return {num} 脱敏之后的手机号
 */
O.desensitizePhone = function (phone) {
  if (phone !== undefined) {
    return phone.replace(/(\d{3})\d{4}(\d{4})/, "$1****$2");
  }
};

/**
 * @desc 获取浏览器内核信息
 * @return {obj}
 * {
    trident: ",    // IE内核
    presto: ",     // opera内核
    webKit: ",     // 苹果、谷歌内核
    gecko: ",      // 火狐内核
    mobile: ",     // 是否为移动终端
    ios: ",        // ios终端
    android: ",    // android终端或者uc浏览器
    iPhone: ",     // 是否为iPhone或者QQHD浏览器
    iPad: ",       // 是否iPad
    webApp: "      // 是否web应该程序，没有头部与底部
  }
  */
O.coreInfo = function () {
  var u = navigator.userAgent;
  return {
    trident: u.indexOf("Trident") > -1,
    presto: u.indexOf("Presto") > -1,
    webKit: u.indexOf("AppleWebKit") > -1,
    gecko: u.indexOf("Gecko") > -1 && u.indexOf("KHTML") === -1,
    mobile: !!u.match(/AppleWebKit.*Mobile.*/) || !!u.match(/AppleWebKit/), // 此处有问题
    ios: !!u.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/),
    android: u.indexOf("Android") > -1 || u.indexOf("Linux") > -1,
    iPhone: u.indexOf("iPhone") > -1 || u.indexOf("Mac") > -1,
    iPad: u.indexOf("iPad") > -1,
    webApp: u.indexOf("Safari") === -1
  };
};

/**
 * @desc 判断浏览器类型
 * @return {string}
 */
O.uainfo = function () {
  var Sys = {};
  var ua = navigator.userAgent.toLowerCase();
  var s;
  (s = ua.match(/msie ([\d.]+)/)) ? Sys.ie = s[1] : (s = ua.match(/firefox\/([\d.]+)/)) ? Sys.firefox = s[1] : (s = ua.match(/chrome\/([\d.]+)/)) ? Sys.chrome = s[1] : (s = ua.match(/opera.([\d.]+)/)) ? Sys.opera = s[1] : (s = ua.match(/version\/([\d.]+).*safari/)) ? Sys.safari = s[1] : 0;
  if (Sys.ie) return 'IE';
  if (Sys.firefox) return 'Firefox:';
  if (Sys.chrome) return 'Chrome';
  if (Sys.opera) return 'Opera';
  if (Sys.safari) return 'Safari';
};

/**
 * @desc 判断是否是微信内置浏览器
 * @return {bool}
 */
O.isWeixin = function () {
  // 对浏览器的UserAgent进行正则匹配，不含有微信独有标识的则为其他浏览器
  var useragent = navigator.userAgent.toLowerCase();
  if (useragent.match(/MicroMessenger/i) === "microMessenger") {
    return true;
  } else {
    return false;
  }
};

/**
 * @desc 判断是否在app中
 * @return {bool}
 */
O.isApp = function () {
  return (
    window.hasOwnProperty("android") ||
    (window.hasOwnProperty("webkit") &&
      window.webkit.messageHandlers.hasOwnProperty("iphone"))
  );
};

/**
 * @desc 判断当前页面是否在android平台内
 * @return {bool}
 */
O.isAndroid = function () {
  return window.hasOwnProperty("android");
};

/**
 * @desc 判断当前页面是否在iOS平台内
 * @return {bool}
 */
O.isiOS = function () {
  return (
    window.hasOwnProperty("webkit") &&
    window.webkit.messageHandlers.hasOwnProperty("iphone")
  );
};

/**
 * @desc 是否为数组
 * @param {*} obj
 * @return {bool}
 */
O.isArray = function (obj) {
  return Object.prototype.toString.call(obj) === "[object Array]";
};

/**
 * @desc 是否为空数组
 * @param {arr} arr
 * @return {bool} true 空 false 非空
 */
O.isArrayEmpty = function (arr) {
  return this.isArray(arr) && arr.length <= 0;
};

/**
 * @desc 是否为对象
 * @param {*} obj
 * @return {bool}
 */
O.isObject = function (obj) {
  return Object.prototype.toString.call(obj) === "[object Object]";
};

/**
 * @desc 是否为函数
 * @param {*} obj
 * @return {bool} 校验结果
 */
O.isFunc = function (obj) {
  return (
    Object.prototype.toString.call(obj) === "[object Function]"
  );
};

/**
 * @desc 判断数组中是否有重复项
 * @param {arr} arr
 * @return {bool} 校验结果
 */
O.isArrHasRepeat = function (arr) {
  var obj = {};
  for (var i in arr) {
    if (obj[arr[i]]) {
      return true;
    }
    obj[arr[i]] = true;
  }
  return false;
};

/**
 * @desc 小于10的数之前补零
 * @param {num|str} n
 * @return {str} 补零之后字符串
 */
O.addZero = function (n) {
  return n < 10 ? "0" + n : "" + n;
};

/* @desc 格式化时间
* @param {date为具体的日期，rule为不同的日期格式}
  如:(new Date(),"yyyy/MM/dd")=>"2018/04/23",
  (new Date(),"yyyy/MM/dd hh:mm:ss")=>"2018/04/23 08:09:04"
  (new Date(),"yyyy/MM/dd hh:mm:ss.S")=>"2018/04/23 08:09:06.423"
  (new Date(),"yyyy/MM/dd E hh:mm:ss")=>"2018/04/23 二 20:09:04"
  (new Date(),"yyyy/MM/dd EE hh:mm:ss")=>"2018/04/23 周二 20:09:04"
  (new Date(),"yyyy/MM/dd EEE hh:mm:ss")=>"2018/04/23 星期二 20:09:04"
  (new Date(),"yyyy-MM-dd")=>"2018-04-23"
  (new Date(),"yyyy-MM-dd hh:mm:ss")=>"2018-04-23 08:09:04"
  (new Date(),"yyyy-MM-dd hh:mm:ss.S")=>"2018-04-23 08:09:06.423"
  (new Date(),"yyyy-MM-dd E hh:mm:ss")=>"2018-04-23 二 20:09:04"
  (new Date(),"yyyy-MM-dd EE hh:mm:ss")=>"2018-04-23 周二 20:09:04"
  (new Date(),"yyyy-MM-dd EEE hh:mm:ss")=>"2018-04-23 星期二 20:09:04"
* @return {按照不同的rule格式化后的日期}
*/
O.formatDateForRule = function (date, rule) {
  var showDay = ["一", "二", "三", "四", "五", "六", "日"];
  var t = new Date(date);
  var y = t.getFullYear();
  var M = t.getMonth() + 1;
  var d = t.getDate();
  var w = t.getDay();
  var h = t.getHours();
  var m = t.getMinutes();
  var s = t.getSeconds();
  var ss = t.getMilliseconds();
  M = this.addZero(M);
  d = this.addZero(d);
  h = this.addZero(h);
  m = this.addZero(m);
  s = this.addZero(s);
  var nowTime;
  switch (rule) {
    case "yyyy/MM/dd":
      nowTime = y + "/" + M + "/" + d;
      break;
    case "yyyy/MM/dd hh:mm:ss":
      nowTime = y + "/" + M + "/" + d + " " + h + ":" + m + ":" + s;
      break;
    case "yyyy/MM/dd hh:mm:ss.S":
      nowTime =
        y + "/" + M + "/" + d + " " + h + ":" + m + ":" + s + "." + ss;
      break;
    case "yyyy/MM/dd E hh:mm:ss":
      nowTime =
        y +
        "/" +
        M +
        "/" +
        d +
        " " +
        showDay[w - 1] +
        " " +
        h +
        ":" +
        m +
        ":" +
        s +
        "." +
        ss;
      break;
    case "yyyy/MM/dd EE hh:mm:ss":
      nowTime =
        y +
        "/" +
        M +
        "/" +
        d +
        " 周" +
        showDay[w - 1] +
        " " +
        h +
        ":" +
        m +
        ":" +
        s;
      break;
    case "yyyy/MM/dd EEE hh:mm:ss":
      nowTime =
        y +
        "年" +
        M +
        "月" +
        d +
        "日" +
        " 星期" +
        showDay[w - 1] +
        " " +
        h +
        ":" +
        m +
        ":" +
        s;
      break;
    case "yyyy-MM-dd":
      nowTime = y + "-" + M + "-" + d;
      break;
    case "yyyy-MM-dd hh:mm:ss":
      nowTime = y + "-" + M + "-" + d + " " + h + ":" + m + ":" + s;
      break;
    case "yyyy-MM-dd hh:mm:ss.S":
      nowTime =
        y + "-" + M + "-" + d + " " + h + ":" + m + ":" + s + "." + ss;
      break;
    case "yyyy-MM-dd E hh:mm:ss":
      nowTime =
        y +
        "-" +
        M +
        "-" +
        d +
        " " +
        showDay[w - 1] +
        " " +
        h +
        ":" +
        m +
        ":" +
        s +
        "." +
        ss;
      break;
    case "yyyy-MM-dd EE hh:mm:ss":
      nowTime =
        y +
        "-" +
        M +
        "-" +
        d +
        " 周" +
        showDay[w - 1] +
        " " +
        h +
        ":" +
        m +
        ":" +
        s;
      break;
    case "yyyy-MM-dd EEE hh:mm:ss":
      nowTime =
        y +
        "年" +
        M +
        "月" +
        d +
        "日" +
        " 星期" +
        showDay[w - 1] +
        " " +
        h +
        ":" +
        m +
        ":" +
        s;
      break;
  }
  return nowTime;
};

/**
 * @desc 时间戳转年月日
 * @param {str} ns 时间戳
 * @param {str} symbol （可选，默认为 "-" ）
 * @example formatDate(new Date())
 * @return 返回 2018-07-24
 */
O.formatDate = function (nS, symbol) {
  symbol = symbol !== "" && symbol ? symbol : "-";
  var DD = new Date(Number(nS));
  var year = this.addZero(DD.getFullYear());
  var month = this.addZero(DD.getMonth() + 1);
  var day = this.addZero(DD.getDate());
  var time = year + symbol + month + symbol + day;
  return time;
};

/**
 * @desc 格式化时间字符串，将毫秒数转化成时间格式
 * @param {str} _longtime    毫秒数，字符串
 * @return {str}     时间格式：hh:mm:ss  19:09:56
 */
O.formatTime = function (_longtime) {
  if (_longtime) {
    var longtime = Number(_longtime);
    var date = new Date(longtime);
    var _hour = date.getHours(); // 时
    var _minute = date.getMinutes(); // 分
    var _second = date.getSeconds(); // 秒
    if (_hour < 10) {
      _hour = "0" + _hour;
    }
    if (_minute < 10) {
      _minute = "0" + _minute;
    }
    if (_second < 10) {
      _second = "0" + _second;
    }
    return _hour + ":" + _minute + ":" + _second;
  }
};

/**
 * 时长格式转换
 * 00:00:00
 * @param{String} 秒
 */
O.formatSeconds = function (value) {
  let secondTime = parseInt(value); // 秒
  let minuteTime = 0; // 分
  let hourTime = 0; // 小时
  if (secondTime > 60) {
    // 如果秒数大于60，将秒数转换成整数
    // 获取分钟，除以60取整数，得到整数分钟
    minuteTime = parseInt(secondTime / 60);
    // 获取秒数，秒数取佘，得到整数秒数
    secondTime = parseInt(secondTime % 60);
    // 如果分钟大于60，将分钟转换成小时
    if (minuteTime > 60) {
      // 获取小时，获取分钟除以60，得到整数小时
      hourTime = parseInt(minuteTime / 60);
      // 获取小时后取佘的分，获取分钟除以60取佘的分
      minuteTime = parseInt(minuteTime % 60);
    }
  }
  let result = "";
  if (secondTime > 0) {
    if (secondTime < 10) {
      result = "0" + parseInt(secondTime);
    } else {
      result = parseInt(secondTime);
    }
  } else {
    result = "00";
  }
  if (minuteTime > 0) {
    if (minuteTime < 10) {
      result = "0" + parseInt(minuteTime) + ":" + result;
    } else {
      result = parseInt(minuteTime) + ":" + result;
    }
  } else {
    result = "00:" + result;
  }
  if (hourTime > 0) {
    if (hourTime < 10) {
      result = "0" + parseInt(hourTime) + ":" + result;
    } else {
      result = parseInt(hourTime) + ":" + result;
    }
  } else {
    result = "00:" + result;
  }
  return result;
};

/**
 * @desc 函数防抖(短时间内多次触发同一事件，只执行最后或者最开始的一次，中间的不执行。)
 * @param {fn} func 目标函数
 * @param {num} wait 延迟执行毫秒数 默认1000ms
 * @param {bool} immediate （可选，默认false） true - 立即执行， false - 延迟执行
 */
O.debounce = function (func, wait = 1000, immediate) {
  immediate = immediate !== "" && immediate ? immediate : false;
  let timer;
  return function () {
    let context = this;
    let args = arguments;
    if (timer) clearTimeout(timer);
    if (immediate) {
      let callNow = !timer;
      timer = setTimeout(() => {
        timer = null;
      }, wait);
      if (callNow) func.apply(context, args);
    } else {
      timer = setTimeout(() => {
        func.apply(context, args);
      }, wait);
    }
  };
};

/**
 * @desc 函数节流(指连续触发事件但是在 n 秒中只执行一次函数。即 2n 秒内执行 2 次... 。节流如字面意思，会稀释函数的执行频率。)
 * @param {fn} func 函数
 * @param {num} wait 延迟执行毫秒数 默认1000ms
 * @param {num|str}type (可选，默认1) 1 - 表时间戳版，2 - 表定时器版
 */
O.throttle = function (func, wait = 1000, type) {
  type = type !== "" && type ? Number(type) : 1;
  if (type === 1) {
    var previous = 0;
  } else if (type === 2) {
    var timeout;
  }
  return function () {
    let context = this;
    let args = arguments;
    if (type === 1) {
      let now = Date.now();
      if (now - previous > wait) {
        func.apply(context, args);
        previous = now;
      }
    } else if (type === 2) {
      if (!timeout) {
        timeout = setTimeout(() => {
          timeout = null;
          func.apply(context, args);
        }, wait);
      }
    }
  };
};

/**
 * 随机数
 * flag-是否任意长度 true 任意长度 false 固定长度
 * min-任意长度最小位[固定位数] max-任意长度最大位
 * setRandomString(true, 3, 16)
 * setRandomString(false, 16)
 */
O.setRandomString = function (flag, min, max) {
  let randomStr = "_";
  let range = min;
  let arr = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'];

  // 随机产生
  if (flag) {
    range = Math.round(Math.random() * (max - min)) + min;
  }
  for (let i = 0; i < range; i++) {
    let pos = Math.round(Math.random() * (arr.length - 1));
    randomStr += arr[pos];
  }
  return randomStr;
}

/**
 * @desc 对象合并（目标对象与源对象有同名属性，或多个源对象有同名属性，则后面的属性会覆盖前面的属性）
 * @param {obj} target
 * @param {obj} ...source
 * @return {obj}
 */
O.merging = function (target, ...source) {
  Object.assign(target, ...source);
  return target;
};

/**
 * @desc 浅拷贝
 * @param {obj} source
 * @return {obj} 返回新对象
 * 源对象的【属性】是【普通类型】改变之后新对象【不会】改变
 * 源对象的【属性】是【引用类型】改变后新对象也【会】改变
 */
O.shallowClone = function (source) {
  return Object.assign({}, source);
};

/**
 * @desc 浅拷贝(经递归处理，同样应用于多层嵌套)
 * @param {obj} source
 * @return {obj} 返回新对象
 * 返回的新对象和源对象没有关系，不会随源对象改变而改变
 */
O.deepClone = function (source) {
  let result;
  // 如果当前需要深拷贝的是一个对象的话
  if (typeof source === 'object') {
    // 如果是一个数组的话
    if (Array.isArray(source)) {
      result = []; // 将result赋值为一个数组，并且执行遍历
      for (let i in source) {
        // 递归克隆数组中的每一项
        result.push(this.deepClone(source[i]));
      }
      // 判断如果当前的值是null的话；直接赋值为null
    } else if (source === null) {
      result = null;
      // 判断如果当前的值是一个RegExp对象的话，直接赋值
    } else if (source.constructor === RegExp) {
      result = source;
    } else {
      // 否则是普通对象，直接for in循环，递归赋值对象的所有值
      result = {};
      for (let i in source) {
        result[i] = this.deepClone(source[i]);
      }
    }
    // 如果不是对象的话，就是基本数据类型，那么直接赋值
  } else {
    result = source;
  }
  return result;
};

/**
 * @desc Html String 转 Node
 * @param {str} htmlString  html字符串
 * @returns {obj} Node
 */
O.parseElement = function (htmlString) { // Html String 转 Node
  return new DOMParser().parseFromString(htmlString, 'text/html').body.childNodes[0];
}

O.formatFileSize = function (value) {
  if (null == value || value == '') {
    return "0 Bytes";
  }
  var unitArr = new Array("Bytes", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB");
  var index = 0;
  var srcsize = parseFloat(value);
  index = Math.floor(Math.log(srcsize) / Math.log(1024));
  var size = srcsize / Math.pow(1024, index);
  size = size.toFixed(2);//保留的小数位数
  return size + unitArr[index];
}

export default O;
